﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Math;
using AForge.GestureRecognition;
using AForge.Video;


namespace OpenPhysX
{
    public class PhysXGestureRec
    {
        private double physXCoefficient = 0.3;

        private double physXHandsMinProp = 0.3;

        private double physXHandsMinStraightProp = 1.33;

        private double physXHandsDiagoUpProp = 0.35;

        public double PhysXCoefficient
        {
            get { return physXCoefficient; }
            set { physXCoefficient = Math.Max(0, Math.Min(1, value)); }

        }
        public double PhysXHandsMinProp
        {
            get { return physXHandsMinProp; }
            set { physXHandsMinProp = Math.Max(0, value); }

        }
        public double PhysXHandsMinStraightProp
        {
            get { return physXHandsMinStraightProp; }
            set { physXHandsMinStraightProp = Math.Max(0, value); }

        }
        public double PhysXHandsDiagoUpProp
        {
            get { return physXHandsDiagoUpProp; }
            set { physXHandsDiagoUpProp = Math.Max(0, value); }

        }
        public PhysXGestureRec( ) { }

        public Gesture Recognize( Bitmap image, bool bodyImageOnly )
        {
            if (image.PixelFormat != PixelFormat.Format8bppIndexed)
            {
                throw new ArgumentException("Source image can be binary (8 bpp indexed) only");
            }
            BitmapData imageData = image.LockBits(
                new Rectangle(0, 0, image.Width, image.Height),
                ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);

            
            Gesture gesture = Recognize( imageData, bodyImageOnly );

            image.UnlockBits(imageData);

            return gesture;
        }
        public Gesture Recognize( BitmapData imageData, bool bodyImageOnly )
        {
            
            if (imageData.PixelFormat != PixelFormat.Format8bppIndexed)
            {
                throw new ArgumentException("Source image can be binary (8 bpp indexed) only");

            }
            Gesture gesture = new Gesture(HandPosition.NotRaised, HandPosition.NotRaised);

            Bitmap bodyImage = null;
            BitmapData bodyImageData = null;

            if (bodyImageOnly == false)
            {
                Shrink shrinkFilter = new Shrink();
                bodyImage = shrinkFilter.Apply(imageData);

                bodyImageData = bodyImage.LockBits(
                    new Rectangle(0, 0, bodyImage.Width, bodyImage.Height),
                    ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);


            }
            else
            {
                bodyImageData = imageData;


            }
            int bodyWidth = bodyImageData.Width;
            int bodyHeight = bodyImageData.Height;

            HorizontalIntensityStatistics his = new HorizontalIntensityStatistics(imageData);
            int[] hisValues = (int[])his.Gray.Values.Clone();

            double physXLimit = physXCoefficient * bodyHeight;

            for (int i = 0; i < bodyWidth; i++)
            {
                hisValues[i] = ((double)hisValues[i] / 255 > physXLimit) ? 1 : 0;

            }
            return gesture;

        }


    }
}
